﻿using System;
using System.Collections.Generic;
using System.Text;
using Pretext.Arguments;
using System.IO;

namespace Pretext {
	class Program {

		static string rootWorkingDirectory = Environment.CurrentDirectory;

		static int FilesProcessedTotal = 0;
		static int ErrorCount = 0;
		static int WarningCount = 0;

		static int Main(string[] args) {

			int returnValue = 0;

			PretextManager manager = null;
			bool process = true;

			if (args.Length == 0) {

				WriteUsage();
				process = ProcessCurrentDirPrompt();

				if (process)
					args = new string[]{
						"." ,
						"/p" ,
						"/s"
					};

			}

			if (process) {

				try {

					manager = new PretextManager(Pretexter.Session);

					manager.LogItem += new EventHandler<Pretext.Logging.LogEventArgs>(manager_LogItemAdded);
					manager.FileBeingProcessed += new EventHandler<FileEventArgs>(manager_FileBeingProcessed);
					manager.FileSaved += new EventHandler<FileEventArgs>(manager_FileSaved);

					// process the arguments
					manager.ProcessArguments(args);

					// set the root working directory
					rootWorkingDirectory = manager.SourceDirectory;

					// process pretext files
					manager.Process();

				} catch (PretextException ex) {

					string exceptionTypeName = ex.GetType().Name;
					exceptionTypeName = exceptionTypeName.Substring(0, exceptionTypeName.Length - "Exception".Length);

					Console.WriteLine();
					Console.WriteLine("--- Oops, something went wrong - {0} ---", exceptionTypeName);
					Console.WriteLine();

					Console.WriteLine(ex.Message);
					Console.WriteLine(ex.ToString());

					returnValue = 1;

				} catch (Exception ex) {

					Console.WriteLine();
					Console.WriteLine("A fatal error occoured");
					Console.WriteLine();

					Console.WriteLine(ex.Message);
					Console.WriteLine(ex.ToString());

					returnValue = 1;

				}

			}

			WriteSummary();

			if (manager != null) {
				if (manager.Prompt) {

					Console.WriteLine();
					Console.WriteLine("Press any key to continue...");
					Console.ReadKey();

				}
			}

			return returnValue;

		}

		static void manager_LogItemAdded(object sender, Pretext.Logging.LogEventArgs e) {

			if (((PretextManager) sender).VerboseMode || e.LogItem.Type == Pretext.Logging.LogItemType.Error || e.LogItem.Type == Pretext.Logging.LogItemType.HigherLevelInfo) {
				Console.WriteLine(e.LogItem.ToOutputString());
			}

			if (e.LogItem.Type == Pretext.Logging.LogItemType.Error)
				ErrorCount++;

			if (e.LogItem.Type == Pretext.Logging.LogItemType.Warning)
				WarningCount++;

		}

		static void manager_FileBeingProcessed(object sender, FileEventArgs e) {

			Console.WriteLine();
			Console.WriteLine("Processing \"{0}\" ...", getFilenameDisplay(e.Filename));
			Console.WriteLine();
			
			FilesProcessedTotal++;

		}
		static void manager_FileSaved(object sender, FileEventArgs e) {

			Console.WriteLine("  saved as \"{0}\"", getFilenameDisplay(e.Filename));

		}

		static void WriteSummary() {

			Console.WriteLine();
			Console.WriteLine("------------------------------------------------------------");

			int successCount = FilesProcessedTotal - ErrorCount;

			Console.WriteLine("Processed: {0}   Success: {1}   Error: {2}   Warnings: {3}", FilesProcessedTotal, successCount, ErrorCount, WarningCount);

		}

		static string getFilenameDisplay(string filename) {

			if (filename.StartsWith(rootWorkingDirectory))
				return filename.Substring(rootWorkingDirectory.Length + 1);

			return filename;

		}

		static void WriteUsage() {

			Console.WriteLine("Text pre-processor");
			Console.WriteLine("");
			Console.WriteLine("PRETEXT source [/v:VARIABLE_NAME[=VALUE]]");
			Console.WriteLine("");
			Console.WriteLine("");

		}


		/// <summary>
		/// Asks the user if they would like to run pretext on the current directory
		/// </summary>
		static bool ProcessCurrentDirPrompt() {

			string input;

			Console.WriteLine("Would you like to run pretext on the current directory? (Y/N)");

			do {

				input = Console.ReadLine();

				switch (input.ToUpper()) {

					case "YES":
					case "Y":

						return true;

					case "NO":
					case "N":

						return false;

					default:

						if (input.ToUpper() != "Q" && input.ToUpper() != "QUIT")
							Console.WriteLine("Please enter \"Y\" or \"N\"");

						break;

				}

			} while (input.ToUpper() != "Q" && input.ToUpper() != "QUIT");

			return false;

		}

	}
}